package com.wwinsoft.framework.service.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.activiti.engine.IdentityService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.wwinsoft.framework.dao.security.AuthorityDao;
import com.wwinsoft.framework.dao.security.GroupDao;
import com.wwinsoft.framework.dao.security.MemberShipDao;
import com.wwinsoft.framework.dao.security.ResourceDao;
import com.wwinsoft.framework.dao.security.RoleAuthorityDao;
import com.wwinsoft.framework.dao.security.UserDao;
import com.wwinsoft.framework.entity.security.Authority;
import com.wwinsoft.framework.entity.security.Group;
import com.wwinsoft.framework.entity.security.MemberShip;
import com.wwinsoft.framework.entity.security.Resource;
import com.wwinsoft.framework.entity.security.RoleAuthority;
import com.wwinsoft.framework.entity.security.User;
import com.wwinsoft.framework.pojo.common.JsNode;
import com.wwinsoft.framework.service.ServiceException;
import com.wwinsoft.modules.orm.Page;
import com.wwinsoft.modules.orm.PropertyFilter;
import com.wwinsoft.modules.security.springsecurity.SpringSecurityUtils;
import com.wwinsoft.oa.dao.plan.WorkPlanDao;

/**
 * 安全相关实体的管理类, 包括用户,角色,资源与授权类.
 *
 * @author calvin
 */
//Spring Bean的标识.
@Component
//默认将类中的所有函数纳入事务管理.
@Transactional
public class AccountManager {

    private static Logger logger = LoggerFactory.getLogger(AccountManager.class);
    private static final Long SUPER_ADMIN = 1l;

    @Autowired
    private UserDao userDao;
    @Autowired
    private GroupDao groupDao;
    @Autowired
    private AuthorityDao authorityDao;

    // add by sevenSpend 2011-11-27 start -->
    @Autowired
    private MemberShipDao memberShipDao;
    // <-- add by sevenSpend 2011-11-27 end
    
    @Autowired
    private RoleAuthorityDao roleAuthorityDao;

    // add by sevenSpend 2011-11-30 start -->
    @Autowired
    private WorkPlanDao workPlanDao;
    // <-- add by sevenSpend 2011-11-30 end
    @Autowired
    private ResourceDao resourceDao;

    //-- User Manager --//
    @Transactional(readOnly = true)
    public User getUser(Long id) {
        User user = userDao.get(id);
        user.setUiGroupIds(userDao.getUIDeptId(id));
        return user;
    }

    public void saveUser(User entity){
        userDao.save(entity);
    }

    public void saveUser(User entity, List<Long> checkedRoleIds , List<Long> checkedDeptIds) {
        userDao.save(entity);
        mergeMembershipByCheckedIds(entity, checkedRoleIds, checkedDeptIds);
    }

    private void mergeMembershipByCheckedIds(User entity, List<Long> checkedRoleIds , List<Long> checkedDeptIds){
        List<Long> checkedGroupIds = Lists.newArrayList();
        checkedGroupIds.addAll(checkedRoleIds);
        checkedGroupIds.addAll(checkedDeptIds);
        Collection<String> aliasIdList = groupDao.getAliasIdList(checkedGroupIds);
        Collection<String> parentAliasIdList =  groupDao.getParentAliasListByChildren(checkedDeptIds);
        for (Iterator<MemberShip> iterator = entity.getMemberShipList().iterator(); iterator.hasNext(); ) {
            MemberShip memberShip = iterator.next();
            String groupId = memberShip.getGroupId();
            if(aliasIdList.contains(groupId)){
                 memberShip.setType(0);
                memberShipDao.save(memberShip);
                 aliasIdList.remove(groupId);
            } else if(parentAliasIdList.contains(groupId)){
                 memberShip.setType(1);
                memberShipDao.save(memberShip);
                 parentAliasIdList.remove(groupId);
            } else{
                memberShipDao.delete(memberShip);
            }
        }

        String useId = entity.getUserId();

        for (String checkedAliasId : aliasIdList) {
              memberShipDao.save(new MemberShip(useId, checkedAliasId, 0));
        }

        for (String halfCheckedGroupId : parentAliasIdList) {
            memberShipDao.save(new MemberShip(useId, halfCheckedGroupId, 1));
        }
    }


    /**
     * 删除用户,如果尝试删除超级管理员将抛出异常.
     */
    public void deleteUser(Long id) {
        if (isSupervisor(id)) {
            logger.warn("操作员{}尝试删除超级管理员用户", SpringSecurityUtils.getCurrentUserName());
            throw new ServiceException("不能删除超级管理员用户");
        }
        userDao.delete(id);
    }

    /**
     * 判断是否超级管理员.
     */
    private boolean isSupervisor(Long id) {
        return SUPER_ADMIN.equals(id);
    }

    /**
     * 使用属性过滤条件查询用户.
     */
    @Transactional(readOnly = true)
    public Page<User> searchUser(final Page<User> page, final List<PropertyFilter> filters) {
        return userDao.findPage(page, filters);
    }

    @Transactional(readOnly = true)
    public List<User> searchUser(final List<PropertyFilter> filters) {
        return userDao.findList(filters);
    }

    @Transactional(readOnly = true)
    public User findUserByLoginName(String loginName) {
        return userDao.getUserByUserId(loginName);
    }

    /**
     * 检查用户名是否唯一.
     *
     * @return loginName在数据库中唯一或等于oldLoginName时返回true.
     */
    @Transactional(readOnly = true)
    public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
        return userDao.isPropertyUnique("userId", newLoginName, oldLoginName);
    }

    //-- Role Manager --//
    @Transactional(readOnly = true)
    public Group getRole(Long id) {
        return groupDao.get(id);
    }

    @Transactional(readOnly = true)
    public Group getGroupWithAuthorityFilter(Long id) {
        return groupDao.getRoleWithAuthorityFilter(id);
    }

    @Transactional(readOnly = true)
    public List<Group> getAllRole() {
        return groupDao.getAllRole();
    }

    @Transactional(readOnly = true)
    public List<Group> getAllDept() {
        return groupDao.getAllDept();
    }

    // add by sevenSpend 2011-11-26 start -->
    /**
     * 获取部门列表
     * 
     * @return
     */
    @Transactional(readOnly = true)
    public List<Group> getDeptList() {
        return groupDao.getDeptList();
    }
    
    /**
     * 根据上级部门ID获取下级部门
     * 
     * @return
     */
    @Transactional(readOnly = true)
    public List<Group> getDeptByParentId(Long parentId) {
        return groupDao.getDeptByParentId(parentId);
    }
    
    /**
     * 根据部门类型获取部门列表
     * 
     * @return
     */
    @Transactional(readOnly = true)
    public List<Group> getDeptByCategory() {
        return groupDao.getDeptByCategory();
    } 
    
    @Transactional(readOnly = true)
    public String getDeptNameById(Long id){
        Group group = groupDao.get(id);
        return group.getName();
    }   
    
    /**
     * 根据用户ID获取会员关系列表
     * 
     * @param userId
     * @return
     */
    @Transactional(readOnly = true)
    public List<Object[]> getMemberShipListByUserId(String userId) {
        return memberShipDao.getMemberShipListByUserId(userId);
    }
    
    /**
     * 获取全部组织
     * 
     * @return
     */
    @Transactional(readOnly = true)
    public List<Group> getAllGroup() {
        return groupDao.getAllGroup();
    }    

    /**
     * 保存部门
     * 
     * @param entity 部门实体
     */
    public void saveGroupInfo(Group entity, List<Long> checkedAuthIdList) {
    	// 保存部门
        groupDao.save(entity);

        // 部门ID有变更时，联动更新会员组织关系表
        if (!entity.getOrginDeptId().equals(entity.getDeptId())) {
        	// 更新会员组织关系表
        	memberShipDao.updateGroupId(entity.getOrginDeptId(), entity.getDeptId());
        }

        mergeRoleAuthByCheckedIds(entity, checkedAuthIdList);
    }

    private void mergeRoleAuthByCheckedIds(Group entity, List<Long> checkedAuthIdList){
        if(checkedAuthIdList==null){
            return;
        }
        Collection<Long> halfCheckedAuthIds =  authorityDao.getParentsByChildren(checkedAuthIdList);
        for (RoleAuthority roleAuthority : entity.getRoleAuthorityList()) {
            if(checkedAuthIdList.contains(roleAuthority.getAuthorityId())){
                 roleAuthority.setType(0);
                roleAuthorityDao.save(roleAuthority);
                checkedAuthIdList.remove(roleAuthority.getAuthorityId());
            } else if(halfCheckedAuthIds.contains(roleAuthority.getAuthorityId())){
                 roleAuthority.setType(1);
                roleAuthorityDao.save(roleAuthority);
                halfCheckedAuthIds.remove(roleAuthority.getAuthorityId());
            }else{
               roleAuthorityDao.delete(roleAuthority);
            }
        }

        Long groupId = entity.getId();
        for (Long checkedGroupId : checkedAuthIdList) {
              roleAuthorityDao.save(new RoleAuthority(groupId,checkedGroupId,0));
        }

        for (Long halfCheckedGroupId : halfCheckedAuthIds) {
            roleAuthorityDao.save(new RoleAuthority(groupId,halfCheckedGroupId,1));
        }
    }

    /**
     * 删除部门
     * 
     * @param id
     * @param groupId 部门ID
     */
    public void deleteGroupInfo(Long id, String groupId) {
    	// 删除部门
        groupDao.delete(id);
        
        // 联动删除会员组织关系表、工作计划表
        memberShipDao.deleteByGroupId(groupId);
        
        // add by sevenSpend 2011-11-30 start -->
        workPlanDao.deleteByGroupId(groupId);
        // <-- add by sevenSpend 2011-11-30 end
    }
    // <-- add by sevenSpend 2011-11-27 end

    // add by sevenSpend 2011-11-30 start -->
    /**
     * 根据部门ID获取会员关系列表
     * 
     * @param groupId
     * @return
     */
    @Transactional(readOnly = true)
    public List<Object[]> getMemberShipListByGroupId(String groupId) {
        return memberShipDao.getMemberShipListByGroupId(groupId);
    }

    public void deleteRole(Long id) {
        groupDao.delete(id);
    }

    //-- Authority Manager --//
    @Transactional(readOnly = true)
    public List<Authority> getAllAuthority() {
        return authorityDao.getAll("position", true);
    }


    public Long updateNode(JsNode<Long> jsNode) throws Exception {
        if ("remove_node".equalsIgnoreCase(jsNode.getOperation())) {
            groupDao.deleteAllChildrenBySQL(jsNode.getId());
            return jsNode.getId();
        }

        if (("move_node").equalsIgnoreCase(jsNode.getOperation()) && jsNode.isCopy()) {
            Group oldGroup = groupDao.get(jsNode.getId());
            jsNode.setName(oldGroup.getName());
            jsNode.setType(oldGroup.getNodeType());
            jsNode.setId(null);
        }

        Group group;
        if (jsNode.getId() != null) {
            group = groupDao.get(jsNode.getId());
        } else {
            group = new Group();
        }
        if (StringUtils.isNotEmpty(jsNode.getName())) {
            group.setName(jsNode.getName());
        }
        if (jsNode.getRevision() != null) {
            group.setRevision(jsNode.getRevision());
        }
        if (jsNode.getParentId() != null) {
            group.setParentId(jsNode.getParentId());
        }
        group.popDeptBaseInfo();
        groupDao.save(group);
        return group.getId();
    }

    /**
     * 查找URL类型的资源并初始化可访问该资源的授权.
     */
    @Transactional(readOnly = true)
    public List<Resource> getUrlResourceWithAuthorities() {
        return resourceDao.getUrlResourceWithAuthorities();
    }

}
